package com.sugon.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.sugon.dao.*;
import com.sugon.entity.*;
import com.sugon.modules.sparepart.model.vo.SparePartRequDetailVO;
import com.sugon.modules.sys.consts.CommonConstant;
import com.sugon.modules.sys.consts.MsCenterNoticeType;
import com.sugon.modules.sys.consts.SysRole;
import com.sugon.modules.sys.model.dto.NoticeModel;
import com.sugon.modules.sys.service.INoticeManager;
import com.sugon.service.*;
import com.sugon.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * ICHANGAN消息中心通知推送实现类
 *
 * @author YuXD
 * @since 2022-04-13
 */
@Slf4j
@Service
public class MsCenterNoticeManagerImpl implements INoticeManager {

    @Resource
    private SysUserRoleService userRoleService;
    @Resource
    private DevMaintenWorkService devMaintenWorkService;
    @Resource
    private SysUserService userService;
    @Resource
    private SysConfigService configService;
    @Resource
    private DeviceInfoService deviceInfoService;
    @Resource
    private DevMaintenanceTicketService devPmTicketService;
    @Resource
    private DevAmTicketService devAmTicketService;
    @Resource
    private ModuleMaintainPlanService moduleMaintainPlanService;
    @Resource
    private ModuleArchivesService moduleArchivesService;
    @Resource
    private SysRoleDao roleDao;
    @Resource
    private SysUserDao userDao;
    @Resource
    private SparePartRequDao sparePartRequDao;
    @Resource
    private SysAnnouncementMapper announcementMapper;
    @Resource
    private SysAnnouncementSendMapper announcementSendMapper;

    @Override
    public void pushCancelTransitNotice(SparePartRequDetailVO partNeedsItem, String operator, Integer deliveryNum) {
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.SP_CANCEL_TRANSIT;
        // 创建通知用户列表：需求用户+各个车间的设备技术室主管
        Set<String> noticeUsers = CollectionUtil.newHashSet();
        // 获取需求用户
        SysUserEntity organUser = userService.queryObject(partNeedsItem.getOrganUser());
        Assert.notNull(organUser);
        noticeUsers.add(organUser.getUserName());
        // 额外增加当前车间的设备技术室主管 用户
        List<SysUserEntity> zgUsers = userRoleService.queryDeptUserByRoleId(StrUtil.sub(organUser.getDeptId(), 0, 4), SysRole.CJSBJSSZG.getRoleId(), SysRole.ZZCSBJSSZG.getRoleId());
        if (CollectionUtil.isNotEmpty(zgUsers)) {
            noticeUsers.addAll(zgUsers.stream().map(SysUserEntity::getUserName).collect(Collectors.toList()));
        }
        // 获取备件需求计划
        SparePartRequEntity partNeeds = sparePartRequDao.queryObject(partNeedsItem.getPlanId());
        Assert.notNull(partNeeds);
        String content = StrUtil.format(noticeType.getNoticeTemplate(), partNeeds.getOrganMonth(), partNeedsItem.getMaterialName(), partNeedsItem.getSpec(), deliveryNum, partNeedsItem.getRemark());
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(CollectionUtil.join(noticeUsers, ","), operator, noticeType.getTitle(), content);
        pushNotice(noticeModel);
    }

    @Override
    public void pushLldspNotice(MaterialBaseEntity materialBase) {
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.LLD_SP;
        // 获取审批用户信息
        SysUserEntity approverUser = materialBase.getApproverUser();
        Assert.notNull(approverUser, "审批用户不存在，请联系管理员！");
        // 获取申请用户信息
        SysUserEntity organUser = userService.queryObject(materialBase.getPicker());
        Assert.notNull(organUser);
        String content = StrUtil.format(noticeType.getNoticeTemplate(), materialBase.getMaterCode(), organUser.getNickName());
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(approverUser.getUserName(), organUser.getUserName(), noticeType.getTitle(), content);
        pushNotice(noticeModel);
    }

    @Override
    public void pushDeliveryNotice(SparePartRequDetailVO partNeedsItem, String operator, Integer deliveryNum) {
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.SP_DELIVERY;
        // 创建通知用户列表：需求用户+各个车间的设备技术室主管
        Set<String> noticeUsers = CollectionUtil.newHashSet();
        // 获取需求用户
        SysUserEntity organUser = userService.queryObject(partNeedsItem.getOrganUser());
        Assert.notNull(organUser);
        noticeUsers.add(organUser.getUserName());
        // 额外增加当前车间的设备技术室主管 用户
        List<SysUserEntity> zgUsers = userRoleService.queryDeptUserByRoleId(StrUtil.sub(organUser.getDeptId(), 0, 4), SysRole.CJSBJSSZG.getRoleId(), SysRole.ZZCSBJSSZG.getRoleId());
        if (CollectionUtil.isNotEmpty(zgUsers)) {
            noticeUsers.addAll(zgUsers.stream().map(SysUserEntity::getUserName).collect(Collectors.toList()));
        }
        // 获取备件需求计划
        SparePartRequEntity partNeeds = sparePartRequDao.queryObject(partNeedsItem.getPlanId());
        Assert.notNull(partNeeds);
        String content = StrUtil.format(noticeType.getNoticeTemplate(), partNeedsItem.getApplyUnit(), organUser.getNickName(), partNeeds.getOrganMonth(), partNeedsItem.getMaterialName(), partNeedsItem.getSpec(), deliveryNum);
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(CollectionUtil.join(noticeUsers, ","), operator, noticeType.getTitle(), content);
        pushNotice(noticeModel);
        // 生成站内通知
        generateStationMessage("备件", "备件到货", "备件到货通知", content, CommonConstant.MSG_CATEGORY_2, "url", "http://erms.changan.com/erms/ermsSSO/spare/sparestorepos?spareId=" + partNeedsItem.getMaterialId(), partNeedsItem.getOrganUser());
    }

    @Override
    public void pushSpCatUnSetNotice(SparePartEntity sp) {
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.SP_CAT_UNSET;
        String content = StrUtil.format(noticeType.getNoticeTemplate(), sp.getName(), sp.getSpec(), sp.getPartCode());
        // 发送通知，默认推送给袁西，张丽华
        NoticeModel noticeModel = new NoticeModel("31977,34362", ShiroUtils.getUserName(), noticeType.getTitle(), content);
        pushNotice(noticeModel);
    }

    /**
     * 推送站内消息
     *
     * @param busType          业务类型
     * @param secondaryBusType 子业务类型
     * @param title            标题
     * @param msgContent       消息内容
     * @param msgCategory      消息分类
     * @param openType         打开方式
     * @param openPage
     * @param userIds
     */
    @Override
    public void generateStationMessage(String busType, String secondaryBusType, String title, String msgContent, String msgCategory, String openType, String openPage, String userIds) {
        SysAnnouncement sysAnnouncement = new SysAnnouncement();
        sysAnnouncement.setId(RandomUtil.randomString(32));
        sysAnnouncement.setTitle(title);
        sysAnnouncement.setMsgContent(msgContent);
        sysAnnouncement.setSender(ShiroUtils.getUserId());
        sysAnnouncement.setMsgCategory(msgCategory);
        sysAnnouncement.setSendTime(DateUtil.date());
        sysAnnouncement.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
        sysAnnouncement.setBusType(busType);
        sysAnnouncement.setOpenType(openType);
        sysAnnouncement.setOpenPage(openPage);
        sysAnnouncement.setSecondaryBusType(secondaryBusType);
        sysAnnouncement.setUserIds(userIds);
        // 1.插入通告表记录
        announcementMapper.save(sysAnnouncement);
        // 2.插入用户通告阅读标记表记录
        List<String> userIdList = StrUtil.split(userIds, ",");
        String anntId = sysAnnouncement.getId();
        for (int i = 0; i < userIdList.size(); i++) {
            SysAnnouncementSend announcementSend = new SysAnnouncementSend();
            announcementSend.setAnntId(anntId);
            announcementSend.setUserId(userIdList.get(i));
            announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
            announcementSendMapper.save(announcementSend);
        }
    }

    @Override
    public void pushDeviceCallRepairNotice(String businessId) {
        DevMaintenWorkEntity devMaintenWork = devMaintenWorkService.queryObject(businessId);
        Assert.notNull(devMaintenWork, "设备维修工单不存在，工单ID:[{}]", businessId);
        // 找出给谁推送消息：当前车间的维修租场
        List<SysUserEntity> userList = userRoleService.queryDeptRoleUserList(devMaintenWork.getWorkshopId(), SysRole.WXZZ.getRoleId());
        Assert.notEmpty(userList);
        String userLoginIds = CollectionUtil.join(userList.stream().map(SysUserEntity::getUserName).distinct().collect(Collectors.toList()), ",");
        // 谁推送的消息：报修人
        String sendByLoginId = null;
        if (StrUtil.isNotEmpty(devMaintenWork.getUploadId())) {
            SysUserEntity uploader = userService.queryObject(devMaintenWork.getUploadId());
            if (uploader != null) {
                sendByLoginId = uploader.getUserName();
            }
        }
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.DEVICE_BX;
        DeviceInfoEntity device = deviceInfoService.queryObject(devMaintenWork.getDevId());
        Assert.notNull(device);
        String content = StrUtil.format(noticeType.getNoticeTemplate(), device.getDevProductCode(), device.getDevProceNo(), device.getDevName(), devMaintenWork.getFaultCon());
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
        pushNotice(noticeModel);
    }

    @Override
    public void pushKYDevMaintenanceNotice(List<DeviceInfoEntity> deviceList) {
        if (CollectionUtil.isEmpty(deviceList)) {
            return;
        }
        // 获取消息接收人员列表
        String userLoginIds = configService.getValue("KY_DEVICE_MAINTENANCE_USER", "");
        if (StrUtil.isEmpty(userLoginIds)) {
            return;
        }
        // 谁推送的消息：先默认喻总吧，他的需求
        String sendByLoginId = "";
        // 空压设备维护通知类别
        MsCenterNoticeType noticeType = MsCenterNoticeType.KY_DEVICE_MAINTENANCE;
        // 获取待维护的设备列表
        List<String> deviceMsgList = deviceList.stream().map(device -> StrUtil.format("{}-{}-{}下次保养寿命:{},当前运行寿命：{}", device.getDevProductName(), device.getDevProceName(), device.getDevName(), device.getMaintenanceLifeSpan(), device.getCurrentLifeSpan())).collect(Collectors.toList());
        // 设置通知消息内容
        String content = StrUtil.format(noticeType.getNoticeTemplate(), CollectionUtil.join(deviceMsgList, "\n"));
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
        log.info("给用户{}发送消息如下：{}", userLoginIds, content);
        pushNotice(noticeModel);
    }

    @Override
    public void pushUnderSafeStockNotice(String workshop, String sparePartName) {
        // 如果配置用户，则表示无论哪个车间的安全库存不足都会通知到
        Set<String> userSet = CollectionUtil.newHashSet();
        String userStr = configService.getValue("SPARE_PART_UNDER_SAFETY_STOCK_USER", "");
        if (StrUtil.isNotEmpty(userStr)) {
            userSet.addAll(StrUtil.split(userStr, ","));
        }
        // 获取库存不足时待通知的角色用户信息
        String roleStr = configService.getValue("SPARE_PART_UNDER_SAFETY_STOCK_ROLE", "");
        List<SysUserEntity> roleUserList = CollectionUtil.newArrayList();
        if (StrUtil.isNotEmpty(roleStr)) {
            List<SysRoleEntity> roleList = roleDao.listByRoleCode(roleStr);
            if (CollectionUtil.isNotEmpty(roleList)) {
                roleUserList.addAll(userRoleService.queryRoleUserList(roleList));
            }
        }
        // 获取通知用户列表
        userSet.addAll(roleUserList.stream().filter(x -> workshop.equals(x.getDeptCode())).map(SysUserEntity::getUserName).distinct().collect(Collectors.toList()));
        // 设置通知接收人
        String userLoginIds = CollectionUtil.join(userSet, ",");
        // 谁推送的消息：先默认喻总吧，他的需求
        String sendByLoginId = "";
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.UNDER_SAFE_STOCK;
        String content = StrUtil.format(noticeType.getNoticeTemplate(), sparePartName);
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
        pushNotice(noticeModel);
    }

    @Override
    public void pushDeviceCDNotice(String businessId) {
        DevMaintenWorkEntity devMaintenWork = devMaintenWorkService.queryObject(businessId);
        Assert.notNull(devMaintenWork, "设备维修工单不存在，工单ID:[{}]", businessId);
        /*
            给谁推送消息：
            如果已派工，那么给维修人员
            如果未派工，那么给当前车间的维修组长
         */
        String receiveUserId = devMaintenWork.getRepairUser();
        String userLoginIds;
        if (StrUtil.isEmpty(receiveUserId)) {
            List<SysUserEntity> userList = userRoleService.queryDeptUserByRoleId(devMaintenWork.getWorkshopId(), SysRole.WXZZ.getRoleId());
            Assert.notEmpty(userList);
            userLoginIds = CollectionUtil.join(userList.stream().map(SysUserEntity::getUserName).distinct().collect(Collectors.toList()), ",");
        } else {
            // 谁推送的消息：报修人
            SysUserEntity repairUser = userService.queryObject(receiveUserId);
            Assert.notNull(repairUser);
            userLoginIds = repairUser.getUserName();
        }
        // 谁推送的消息：报修人
        SysUserEntity uploader = userService.queryObject(devMaintenWork.getUploadId());
        Assert.notNull(uploader);
        String sendByLoginId = uploader.getUserName();
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.DEVICE_CD;
        DeviceInfoEntity device = deviceInfoService.queryObject(devMaintenWork.getDevId());
        Assert.notNull(device);
        String content = StrUtil.format(noticeType.getNoticeTemplate(), device.getDevProductCode(), device.getDevProceNo(), device.getDevName(), devMaintenWork.getFaultCon());
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
        pushNotice(noticeModel);
    }

    @Override
    public void pushDeviceUploadNotice(String businessId) {

    }

    @Override
    public void pushDeviceMaintenanceNotice(String businessId) {
        DevMaintenanceTicketEntity devMaintenanceTicket = devPmTicketService.queryObject(businessId);
        Assert.notNull(devMaintenanceTicket, "设备维护工单不存在，工单ID:[{}]", businessId);
        String executorStr = devMaintenanceTicket.getExecutor();
        if (StrUtil.isEmpty(executorStr)) {
            return;
        }
        String[] executorArray = executorStr.split(",");
        for (String executor : executorArray) {
            // 找出给谁推送消息：维修人员
            SysUserEntity executorUser = userService.queryObject(executor);
            Assert.notNull(executor);
            String userLoginIds = executorUser.getUserName();
            // 谁推送的消息：当前登录用户
            String sendByLoginId = ShiroUtils.getUserName();
            // 拼接通知内容
            MsCenterNoticeType noticeType = MsCenterNoticeType.DEVICE_WH;
            DeviceInfoEntity device = deviceInfoService.queryObject(devMaintenanceTicket.getDevId());
            Assert.notNull(device);
            String content = StrUtil.format(noticeType.getNoticeTemplate(), device.getDevProductCode(), device.getDevProceNo(), device.getDevName());
            // 发送通知
            NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
            pushNotice(noticeModel);
        }
    }

    @Override
    public void pushDeviceAmNotice(String businessId) {
        DevAmTicketEntity devAmTicket = devAmTicketService.queryObject(businessId);
        Assert.notNull(devAmTicket, "设备维护工单不存在，工单ID:[{}]", businessId);
        String executorStr = devAmTicket.getExecutor();
        if (StrUtil.isEmpty(executorStr)) {
            return;
        }
        String[] executorArray = executorStr.split(",");
        for (String executor : executorArray) {
            // 找出给谁推送消息：维修人员
            SysUserEntity executorUser = userService.queryObject(executor);
            Assert.notNull(executor);
            String userLoginIds = executorUser.getUserName();
            // 谁推送的消息：当前登录用户
            String sendByLoginId = ShiroUtils.getUserName();
            // 拼接通知内容
            MsCenterNoticeType noticeType = MsCenterNoticeType.DEVICE_WH;
            DeviceInfoEntity device = deviceInfoService.queryObject(devAmTicket.getDevId());
            Assert.notNull(device);
            String content = StrUtil.format(noticeType.getNoticeTemplate(), device.getDevProductCode(), device.getDevProceNo(), device.getDevName());
            // 发送通知
            NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
            pushNotice(noticeModel);
        }
    }

    @Override
    public void pushNewlyAddTemMaintenancePlanNotice(String businessId) {
        DevMaintenanceTicketEntity devMaintenanceTicket = devPmTicketService.queryObject(businessId);
        Assert.notNull(devMaintenanceTicket, "设备维修工单不存在，工单ID:[{}]", businessId);
        // 找出对应车间的维修班组长
        List<SysUserEntity> roleUserList = userRoleService.queryDeptUserByRoleId(devMaintenanceTicket.getWorkshop(), SysRole.WXZZ.getRoleId(), SysRole.MXZZ.getRoleId());
        if (CollectionUtil.isEmpty(roleUserList)) {
            return;
        }
        for (SysUserEntity wxzz : roleUserList) {
            // 找出给谁推送消息：维修组长
            String userLoginIds = wxzz.getUserName();
            // 谁推送的消息：当前登录用户
            String sendByLoginId = ShiroUtils.getUserName();
            // 拼接通知内容
            MsCenterNoticeType noticeType = MsCenterNoticeType.DEVICE_WH_NA;
            String content = StrUtil.format(noticeType.getNoticeTemplate(), devMaintenanceTicket.getRepairCode());
            // 发送通知
            NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
            pushNotice(noticeModel);
        }
    }

    @Override
    public void pushNewlyAddTemAmPlanNotice(String businessId) {
        DevAmTicketEntity devAmTicket = devAmTicketService.queryObject(businessId);
        Assert.notNull(devAmTicket, "设备自主维护工单不存在，工单ID:[{}]", businessId);
        // 找出对应车间的维修班组长
        List<SysUserEntity> roleUserList = userRoleService.queryDeptUserByRoleId(devAmTicket.getWorkshop(), SysRole.WXZZ.getRoleId(), SysRole.MXZZ.getRoleId());
        if (CollectionUtil.isEmpty(roleUserList)) {
            return;
        }
        for (SysUserEntity wxzz : roleUserList) {
            // 找出给谁推送消息：维修组长
            String userLoginIds = wxzz.getUserName();
            // 谁推送的消息：当前登录用户
            String sendByLoginId = ShiroUtils.getUserName();
            // 拼接通知内容
            MsCenterNoticeType noticeType = MsCenterNoticeType.DEVICE_WH_NA;
            String content = StrUtil.format(noticeType.getNoticeTemplate(), devAmTicket.getRepairCode());
            // 发送通知
            NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
            pushNotice(noticeModel);
        }
    }

    @Override
    public void pushMoldMaintenanceNotice(String businessId) {
        ModuleMaintainPlanEntity moduleMaintainPlan = moduleMaintainPlanService.queryObject(businessId);
        Assert.notNull(moduleMaintainPlan, "模具维护工单不存在，工单ID:[{}]", businessId);
        // 找出给谁推送消息：维修人员
        List<SysUserEntity> repairUserList = userDao.queryUser(moduleMaintainPlan.getRepairUser());
        if (CollectionUtil.isEmpty(repairUserList)) {
            return;
        }
        String userLoginIds = CollectionUtil.join(repairUserList.stream().map(SysUserEntity::getUserName).collect(Collectors.toList()), ",");
        // 谁推送的消息：当前登录用户
        String sendByLoginId = ShiroUtils.getUserName();
        // 拼接通知内容
        MsCenterNoticeType noticeType = MsCenterNoticeType.MOLD_WH;
        ModuleArchivesEntity mold = moduleArchivesService.queryObject(moduleMaintainPlan.getMoldId());
        Assert.notNull(mold);
        String content = StrUtil.format(noticeType.getNoticeTemplate(), mold.getModuleNo());
        // 发送通知
        NoticeModel noticeModel = new NoticeModel(userLoginIds, sendByLoginId, noticeType.getTitle(), content);
        pushNotice(noticeModel);
    }

    /**
     * 发送通知，目前企业微信用的最多，只推送企业微信
     *
     * @param noticeModel 通知model
     */
    private void pushNotice(NoticeModel noticeModel) {
        String remoteServiceHost = configService.getRemoteServiceHost();
        // 给用户企业微信发送通知
        try {
            String postResult = HttpUtil.post(remoteServiceHost + "/mscenter/send/weixWork", BeanUtil.beanToMap(noticeModel));
        } catch (Exception ex) {
            log.info("调用长安消息接口发送企业微信消息失败，原因：" + ex.getMessage());
        }
        //SysLogEntity log = new SysLogEntity();
        //log.setParams(JSON.toJSONString(noticeModel));
        //log.setOperation("推送通知到企业微信");
        //log.setTitle(postResult);
        //logService.save(log);
        //// 给ICHANGAN发送通知
        //String postResult2 = HttpUtil.post(remoteServiceHost + "/mscenter/send/app4.0", BeanUtil.beanToMap(noticeModel));
        //SysLogEntity log2 = new SysLogEntity();
        //log2.setParams(JSON.toJSONString(noticeModel));
        //log2.setOperation("推送通知到ICHANGAN");
        //log2.setTitle(postResult2);
        //logService.save(log2);
    }

}
